Skip to content

feat(window): expose WindowConfig::app_id() and consume launcher activation tokens - #1085

Open
iam2r wants to merge 2 commits into
lapce:lapce-backportsfrom
iam2r:backport-test
Open

feat(window): expose WindowConfig::app_id() and consume launcher activation tokens#1085
iam2r wants to merge 2 commits into
lapce:lapce-backportsfrom
iam2r:backport-test

Conversation

@iam2r

@iam2r iam2r commented Aug 23, 2026

Copy link
Copy Markdown

Problem

Applications built with Floem currently never identify their windows to the
desktop environment:

  1. No application name is requested. create_window builds winit's
    WindowAttributes without ever setting a name, so winit never calls
    set_app_id() on Wayland. On X11 the backend silently falls back to
    deriving WM_CLASS from argv[0], masking the issue.

    Result on GNOME Wayland: the window cannot be associated with any
    .desktop entry — taskbars/docks show a generic icon or an "UNKNOWN"
    label, windows don't group, and launch tracking degrades
    (see Lapce is missing icon in a lot of places for Gnome/Wayland lapce#2199).

  2. Launcher activation tokens are never consumed. When a desktop shell
    launches an app it passes XDG_ACTIVATION_TOKEN (Wayland) /
    DESKTOP_STARTUP_ID (X11) and keeps the launch in a pending state until
    the token is used. Unconsumed, shells fall back to a timeout (~15s on
    GNOME), during which the dock shows a launching animation instead of the
    app entry.

Protocol capture of an affected app confirms no set_app_id is ever sent:

> WAYLAND_DEBUG=1 lapce |& grep app_id      # before: no output at all

Change

This PR adds two small, opt-in capabilities to window creation:

  • WindowConfig::app_id(impl Into<String>) — declares the application
    identity. When set, floem applies it via winit's
    WindowAttributesExtWayland::with_name() / WindowAttributesExtX11::with_name()
    (Wayland app_id, X11 WM_CLASS). When unset, behaviour is exactly as
    before.
  • Activation token consumption — if the process was spawned by a desktop
    launcher, the token reported by
    EventLoopExtStartupNotify::read_token_from_env() is attached with
    WindowAttributesExtStartupNotify::with_activation_token(), letting the
    compositor complete the startup sequence immediately.

Both are #[cfg(target_os = "linux")]; other platforms are untouched.

Why lapce-backports

Lapce pins this branch, so this is where the fix can reach the editor's next
release. I'm happy to port it to main as well once this lands or once the
direction is confirmed (main's new window-creation layout needs a slightly
different patch shape due to the winit-core split).

Testing

  • Built and run against Lapce on Zorin OS (GNOME, Wayland, 2x scale):
    • Before: dock/taskbar shows "UNKNOWN" / no icon; entry appears only after
      ~15s.
    • After: correct application icon immediately on window map.
  • Protocol verification (WAYLAND_DEBUG=1) now shows
    xdg_toplevel.set_app_id("dev.lapce.lapce") before the surface maps.
  • No unit tests added: the behaviour is platform integration (compositor +
    shell side). Happy to add builder-level tests if preferred.

iam2r added 2 commits August 23, 2026 22:08
Allow applications to declare their desktop identity (Wayland app_id /
X11 WM_CLASS class and instance). Desktop environments use it to
associate windows with the application's .desktop entry: dock/taskbar
icons, app grouping and launch tracking.

When unset, behaviour is unchanged: no set_app_id() is sent on Wayland,
and X11 falls back to deriving WM_CLASS from the executable name.
If the process was spawned by a desktop launcher, XDG_ACTIVATION_TOKEN
(Wayland) or DESKTOP_STARTUP_ID (X11) identifies the pending launch
created for it. Passing that token to the window makes the compositor
complete the startup sequence as soon as the first surface maps.

Without this, shells keep applications launched from an app grid in a
"starting" state until a timeout expires (~15s in GNOME), delaying the
dock/taskbar entry and proper focus.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant